hvm: Define a global I/O access bitmap, allowing direct access to port 0x80.
authorkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Thu, 25 Jan 2007 18:20:58 +0000 (18:20 +0000)
committerkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Thu, 25 Jan 2007 18:20:58 +0000 (18:20 +0000)
Signed-off-by: Keir Fraser <keir@xensource.com>
xen/arch/x86/hvm/hvm.c
xen/arch/x86/hvm/svm/svm.c
xen/arch/x86/hvm/svm/vmcb.c
xen/arch/x86/hvm/vmx/vmcs.c
xen/arch/x86/hvm/vmx/vmx.c
xen/include/asm-x86/hvm/support.h
xen/include/asm-x86/hvm/svm/vmcb.h

index 44c6a4473d66b3acd4046ea2af7c94d20418c194..c3ba2b233c1bf0205762df419c22eafa3c6847dd 100644 (file)
 #include <public/version.h>
 #include <public/memory.h>
 
-int hvm_enabled = 0;
+int hvm_enabled;
 
-unsigned int opt_hvm_debug_level = 0;
+unsigned int opt_hvm_debug_level;
 integer_param("hvm_debug", opt_hvm_debug_level);
 
 struct hvm_function_table hvm_funcs;
 
+/* I/O permission bitmap is globally shared by all HVM guests. */
+char __attribute__ ((__section__ (".bss.page_aligned")))
+    hvm_io_bitmap[3*PAGE_SIZE];
+
+void hvm_enable(void)
+{
+    if ( hvm_enabled )
+        return;
+
+    /*
+     * Allow direct access to the PC debug port (it is often used for I/O
+     * delays, but the vmexits simply slow things down).
+     */
+    memset(hvm_io_bitmap, ~0, sizeof(hvm_io_bitmap));
+    clear_bit(0x80, hvm_io_bitmap);
+
+    hvm_enabled = 1;
+}
+
 void hvm_stts(struct vcpu *v)
 {
     /* FPU state already dirty? Then no need to setup_fpu() lazily. */
index 55cc1d713136d581dff1e339118388ffbb7c9a8c..7a656865eb53616da794b5e522ee844d47fa4b58 100644 (file)
@@ -1069,7 +1069,7 @@ int start_svm(void)
     hvm_funcs.init_ap_context = svm_init_ap_context;
     hvm_funcs.init_hypercall_page = svm_init_hypercall_page;
 
-    hvm_enabled = 1;
+    hvm_enable();
 
     return 1;
 }
index 6683bc9d18daf3861bcd8a4272b925e1385177a9..46d98f921585048b5c26a41aaf6652b3f62209c5 100644 (file)
@@ -115,19 +115,12 @@ static int construct_vmcb(struct vcpu *v)
     vmcb->cr_intercepts = ~(CR_INTERCEPT_CR2_READ | CR_INTERCEPT_CR2_WRITE);
 
     /* I/O and MSR permission bitmaps. */
-    arch_svm->iopm  = alloc_xenheap_pages(get_order_from_bytes(IOPM_SIZE));
     arch_svm->msrpm = alloc_xenheap_pages(get_order_from_bytes(MSRPM_SIZE));
-    if ( (arch_svm->iopm == NULL) || (arch_svm->msrpm == NULL) )
-    {
-        free_xenheap_pages(arch_svm->iopm,  get_order_from_bytes(IOPM_SIZE));
-        free_xenheap_pages(arch_svm->msrpm, get_order_from_bytes(MSRPM_SIZE));
+    if ( arch_svm->msrpm == NULL )
         return -ENOMEM;
-    }
-    memset(arch_svm->iopm, 0xff, IOPM_SIZE);
-    clear_bit(PC_DEBUG_PORT, arch_svm->iopm);
     memset(arch_svm->msrpm, 0xff, MSRPM_SIZE);
-    vmcb->iopm_base_pa = (u64)virt_to_maddr(arch_svm->iopm);
     vmcb->msrpm_base_pa = (u64)virt_to_maddr(arch_svm->msrpm);
+    vmcb->iopm_base_pa  = (u64)virt_to_maddr(hvm_io_bitmap);
 
     /* Virtualise EFLAGS.IF and LAPIC TPR (CR8). */
     vmcb->vintr.fields.intr_masking = 1;
@@ -241,13 +234,6 @@ void svm_destroy_vmcb(struct vcpu *v)
     if ( arch_svm->vmcb != NULL )
         free_vmcb(arch_svm->vmcb);
 
-    if ( arch_svm->iopm != NULL )
-    {
-        free_xenheap_pages(
-            arch_svm->iopm, get_order_from_bytes(IOPM_SIZE));
-        arch_svm->iopm = NULL;
-    }
-
     if ( arch_svm->msrpm != NULL )
     {
         free_xenheap_pages(
index dde3a4c201bbe0cbb6a7633e9d18b4e96d6bf8a8..20c3ddf61bf2a559fa1482690c76eaf5f06576f0 100644 (file)
@@ -56,7 +56,7 @@
       CPU_BASED_INVDPG_EXITING |                        \
       CPU_BASED_MWAIT_EXITING |                         \
       CPU_BASED_MOV_DR_EXITING |                        \
-      CPU_BASED_UNCOND_IO_EXITING |                     \
+      CPU_BASED_ACTIVATE_IO_BITMAP |                    \
       CPU_BASED_USE_TSC_OFFSETING )
 
 /* Basic flags for VM-Exit controls. */
@@ -302,6 +302,10 @@ static void construct_vmcs(struct vcpu *v)
     __vmwrite(CPU_BASED_VM_EXEC_CONTROL, vmx_cpu_based_exec_control);
     v->arch.hvm_vcpu.u.vmx.exec_control = vmx_cpu_based_exec_control;
 
+    /* I/O access bitmap. */
+    __vmwrite(IO_BITMAP_A, virt_to_maddr(hvm_io_bitmap));
+    __vmwrite(IO_BITMAP_B, virt_to_maddr(hvm_io_bitmap + PAGE_SIZE));
+
     /* Host data selectors. */
     __vmwrite(HOST_SS_SELECTOR, __HYPERVISOR_DS);
     __vmwrite(HOST_DS_SELECTOR, __HYPERVISOR_DS);
index 9d8a3c64a69c8367d1ac3238eb7bdaa1ed6a9b5a..016fd0926a6b1b40e63b5309dfc35a14e49e7d70 100644 (file)
@@ -1011,9 +1011,6 @@ static void vmx_inject_exception(
 /* Setup HVM interfaces */
 static void vmx_setup_hvm_funcs(void)
 {
-    if ( hvm_enabled )
-        return;
-
     hvm_funcs.disable = stop_vmx;
 
     hvm_funcs.vcpu_initialise = vmx_vcpu_initialise;
@@ -1104,7 +1101,7 @@ int start_vmx(void)
 
     vmx_setup_hvm_funcs();
 
-    hvm_enabled = 1;
+    hvm_enable();
 
     return 1;
 }
index 3d40cd9962e4724dc9b4a6014377b8297af2434a..2d15019bb7a48372ad2350b11669ca9076880eaa 100644 (file)
@@ -90,8 +90,6 @@ enum hval_bitmaps {
       EXCEPTION_BITMAP_BP )
 #endif
 
-#define PC_DEBUG_PORT   0x80
-
 #define VMX_DELIVER_NO_ERROR_CODE  -1
 
 #if HVM_DEBUG
@@ -244,17 +242,19 @@ static inline void hvm_get_buffer(hvm_domain_context_t *h, char *buf, int len)
 #define hvm_get_struct(_h, _p) \
     hvm_get_buffer((_h), (char *)(_p), sizeof(*(_p)))
 
+int hvm_save(struct vcpu*, hvm_domain_context_t *h);
+int hvm_load(struct vcpu*, hvm_domain_context_t *h);
 
-extern int hvm_save(struct vcpu*, hvm_domain_context_t *h);
-extern int hvm_load(struct vcpu*, hvm_domain_context_t *h);
-
-extern int arch_sethvm_ctxt(struct vcpu *v, struct hvm_domain_context *c);
-extern int arch_gethvm_ctxt(struct vcpu *v, struct hvm_domain_context *c);
+int arch_sethvm_ctxt(struct vcpu *v, struct hvm_domain_context *c);
+int arch_gethvm_ctxt(struct vcpu *v, struct hvm_domain_context *c);
 
-extern void shpage_init(struct domain *d, shared_iopage_t *sp);
+void shpage_init(struct domain *d, shared_iopage_t *sp);
 
+extern char hvm_io_bitmap[];
 extern int hvm_enabled;
 
+void hvm_enable(void);
+
 int hvm_copy_to_guest_phys(paddr_t paddr, void *buf, int size);
 int hvm_copy_from_guest_phys(void *buf, paddr_t paddr, int size);
 int hvm_copy_to_guest_virt(unsigned long vaddr, void *buf, int size);
index 65ac95e4eba13982a79a704a29baad6e2d9c0913..2a21cfe0013b1a96d568c787d5ab4a4418b6118e 100644 (file)
@@ -452,7 +452,6 @@ struct vmcb_struct {
 struct arch_svm_struct {
     struct vmcb_struct *vmcb;
     u64                 vmcb_pa;
-    u32                 *iopm;
     u32                 *msrpm;
     u64                 vmexit_tsc; /* tsc read at #VMEXIT. for TSC_OFFSET */
     int                 saved_irq_vector;